﻿
Imports std
Imports centrosphere
Imports planet.storageJobConsumerInternal
Imports command = centrosphere.job.storage.command

'the bridge between islice and iasyncslice, need a locked_slice_wrapper to be around
Public Class slice
    Implements islice

    Private Const datakeyprefix As String = "d."
    Private Shared ReadOnly datakeyprefixlen As Int32 = strlen(datakeyprefix)
    Private Shared Function datakey(ByVal key As String) As String
        assert(Not isemptystring(key))
        Return strcat(datakeyprefix, key)
    End Function

    Private Shared Function tskey(ByVal key As String) As String
        assert(Not isemptystring(key))
        Return strcat("t.", key)
    End Function

    Private Shared Function isdatakey(ByVal key As String, ByRef original As String) As Boolean
        If strsame(key, datakeyprefix, datakeyprefixlen) Then
            original = strmid(key, datakeyprefixlen)
            Return Not isemptystring(original)
        Else
            Return False
        End If
    End Function

    Private ReadOnly s As iasyncslice = Nothing

    Public Sub New(ByVal s As iasyncslice)
        assert(Not s Is Nothing)
        Me.s = s
    End Sub

    Public Function asyncslice() As iasyncslice
        Return s
    End Function

    Private Shared Function workon(ByVal key As String,
                                   ByVal w As _do(Of String, pointer(Of Boolean), eventComb),
                                   ByVal result As pointer(Of Boolean)) As eventComb
        Return workon(key, w, w, result)
    End Function

    Private Shared Function workon(ByVal key As String,
                                   ByVal w1 As _do(Of String, pointer(Of Boolean), eventComb),
                                   ByVal w2 As _do(Of String, pointer(Of Boolean), eventComb),
                                   ByVal result As pointer(Of Boolean)) As eventComb
        Return workon(key, w1, w2,
                      Function(ByRef r As Boolean, ByRef i1 As Boolean, ByRef i2 As Boolean) As Boolean
                          Return eva(result, r AndAlso i1 AndAlso i2)
                      End Function)
    End Function

    Private Shared Function workon(Of T)(ByVal key As String,
                                         ByVal w As _do(Of String, pointer(Of T), eventComb),
                                         ByVal merge As _do(Of Boolean, T, T, Boolean)) As eventComb
        Return workon(key, w, w, merge)
    End Function

    Private Shared Function workon(Of T1, T2)(ByVal key As String,
                                              ByVal w1 As _do(Of String, pointer(Of T1), eventComb),
                                              ByVal w2 As _do(Of String, pointer(Of T2), eventComb),
                                              ByVal merge As _do(Of Boolean, T1, T2, Boolean)) As eventComb
        assert(Not merge Is Nothing)
        Return workon(key, w1, w2, Function(ByRef r1, ByRef i1, ByRef r2, ByRef i2) merge(r1 AndAlso r2, i1, i2))
    End Function

    Private Shared Function workon(Of T)(ByVal key As String,
                                         ByVal w As _do(Of String, pointer(Of T), eventComb),
                                         ByVal merge As _do(Of Boolean, T, Boolean, T, Boolean)) As eventComb
        Return workon(key, w, w, merge)
    End Function

    Private Shared Function workon(Of T1, T2)(ByVal key As String,
                                              ByVal w1 As _do(Of String, pointer(Of T1), eventComb),
                                              ByVal w2 As _do(Of String, pointer(Of T2), eventComb),
                                              ByVal merge As _do(Of Boolean, T1, Boolean, T2, Boolean)) As eventComb
        assert(Not w1 Is Nothing)
        assert(Not w2 Is Nothing)
        assert(Not merge Is Nothing)
        Dim p1 As pointer(Of T1) = Nothing
        Dim p2 As pointer(Of T2) = Nothing
        Dim ec As eventComb = Nothing
        Return New eventComb(Function() As Boolean
                                 If isemptystring(key) Then
                                     Return merge(False, Nothing, False, Nothing) AndAlso
                                            goto_end()
                                 Else
                                     p1 = New pointer(Of T1)()
                                     ec = w1(datakey(key), p1)
                                     assert(Not ec Is Nothing)
                                     Return waitfor(ec) AndAlso
                                            goto_next()
                                 End If
                             End Function,
                             Function() As Boolean
                                 If ec.end_result() Then
                                     p2 = New pointer(Of T2)()
                                     ec = w2(tskey(key), p2)
                                     assert(Not ec Is Nothing)
                                     Return waitfor(ec) AndAlso
                                            goto_next()
                                 Else
                                     Return merge(False, Nothing, False, Nothing) AndAlso
                                            False
                                 End If
                             End Function,
                             Function() As Boolean
                                 If ec.end_result() Then
                                     Return merge(True, +p1, True, +p2) AndAlso
                                            goto_end()
                                 Else
                                     Return merge(True, +p1, False, Nothing) AndAlso
                                            False
                                 End If
                             End Function)
    End Function

    Private Shared Function workon(Of T)(ByVal w As _do(Of pointer(Of T), eventComb),
                                         ByVal r As _do(Of Boolean, T, Boolean)) As eventComb
        assert(Not w Is Nothing)
        assert(Not r Is Nothing)
        Dim p As pointer(Of T) = Nothing
        Dim ec As eventComb = Nothing
        Return New eventComb(Function() As Boolean
                                 p = New pointer(Of T)()
                                 ec = w(p)
                                 Return waitfor(ec) AndAlso
                                        goto_next()
                             End Function,
                             Function() As Boolean
                                 If ec.end_result() Then
                                     Return r(True, +p) AndAlso
                                            goto_end()
                                 Else
                                     Return r(False, Nothing) AndAlso
                                            False
                                 End If
                             End Function)
    End Function

    Public Function read(ByVal key As String,
                         ByVal result As pointer(Of bytes),
                         ByVal ts As pointer(Of Int64)) As eventComb Implements islice.read
        Return workon(key,
                      Function(ByRef k As String, ByRef p As pointer(Of bytes)) As eventComb
                          Return s.read(k, p)
                      End Function,
                      Function(ByRef r As Boolean, ByRef i1 As bytes, ByRef i2 As bytes) As Boolean
                          Dim i As Int64 = 0
                          If r AndAlso
                             Not i1 Is Nothing AndAlso
                             Not i2 Is Nothing AndAlso
                             convertor.toint64(i2, i) Then
                              Return eva(result, i1) AndAlso eva(ts, i)
                          Else
                              Return eva(result, [default](Of bytes)()) AndAlso eva(ts, npos)
                          End If
                      End Function)
    End Function

    Private Delegate Function wm_d(ByVal key As String,
                                   ByVal buff As bytes,
                                   ByVal result As pointer(Of Boolean)) As eventComb

    Private Function wm(ByVal key As String,
                        ByVal buff As bytes,
                        ByVal ts As Int64,
                        ByVal result As pointer(Of Boolean),
                        ByVal d As wm_d) As eventComb
        assert(Not d Is Nothing)
        Return workon(key,
                      Function(ByRef k, ByRef p) d(k, buff, p),
                      Function(ByRef k, ByRef p) s.modify(k, convertor.tobytes(ts), p),
                      result)
    End Function

    Public Function write(ByVal key As String,
                          ByVal buff As bytes,
                          ByVal ts As Int64,
                          ByVal result As pointer(Of Boolean)) As eventComb Implements islice.write
        Return wm(key, buff, ts, result, AddressOf s.write)
    End Function

    Public Function uniqueWrite(ByVal key As String,
                                ByVal buff As bytes,
                                ByVal ts As Int64,
                                ByVal result As pointer(Of Boolean)) As eventComb Implements islice.uniqueWrite
        Dim seek_result As pointer(Of Boolean) = Nothing
        Dim ec As eventComb = Nothing
        Return New eventComb(Function() As Boolean
                                 seek_result = New pointer(Of Boolean)()
                                 ec = seek(key, seek_result)
                                 Return waitfor(ec) AndAlso
                                        goto_next()
                             End Function,
                             Function() As Boolean
                                 If ec.end_result() Then
                                     If +seek_result Then
                                         eva(result, False)
                                         Return goto_end()
                                     Else
                                         ec = modify(key, buff, ts, result)
                                         Return waitfor(ec) AndAlso
                                                goto_next()
                                     End If
                                 Else
                                     Return False
                                 End If
                             End Function,
                             Function() As Boolean
                                 Return ec.end_result() AndAlso
                                        goto_end()
                             End Function)
    End Function

    Public Function delete(ByVal key As String,
                           ByVal result As pointer(Of Boolean)) As eventComb Implements islice.delete
        Return workon(key,
                      Function(ByRef k, ByRef p) s.delete(k, p),
                      result)
    End Function

    Public Function seek(ByVal key As String,
                         ByVal result As pointer(Of Boolean)) As eventComb Implements islice.seek
        Return workon(key,
                      Function(ByRef k, ByRef p) s.seek(k, p),
                      result)
    End Function

    Public Function list(ByVal result As pointer(Of vector(Of String))) As eventComb Implements islice.list
        Return workon(Function(ByRef p As pointer(Of vector(Of String))) As eventComb
                          Return s.list(p)
                      End Function,
                      Function(ByRef r As Boolean, ByRef v As vector(Of String)) As Boolean
                          If r AndAlso Not v Is Nothing Then
                              Dim v2 As vector(Of String) = Nothing
                              v2 = New vector(Of String)()
                              For i As Int64 = 0 To v.size() - 1
                                  Dim o As String = Nothing
                                  If isdatakey(v(i), o) Then
                                      assert(v2.push_back(o))
                                  End If
                              Next
                              Return eva(result, v2)
                          Else
                              Return eva(result, [default](Of vector(Of String))())
                          End If
                      End Function)
    End Function

    Public Function modify(ByVal key As String,
                           ByVal buff As bytes,
                           ByVal ts As Int64,
                           ByVal result As pointer(Of Boolean)) As eventComb Implements islice.modify
        Return wm(key, buff, ts, result, AddressOf s.modify)
    End Function

    Public Function sizeof(ByVal key As String,
                           ByVal result As pointer(Of Int64)) As eventComb Implements islice.sizeof
        Return workon(key,
                      Function(ByRef k As String, ByRef p As pointer(Of Int64)) As eventComb
                          Return s.sizeof(k, p)
                      End Function,
                      Function(ByRef r As Boolean, ByRef i1 As Int64, ByRef i2 As Int64) As Boolean
                          Return eva(result, ifoper(r AndAlso i1 >= 0 AndAlso i2 = sizeofInt64, i1, npos))
                      End Function)
    End Function

    Public Function full(ByVal result As pointer(Of Boolean)) As eventComb Implements islice.full
        Return s.full(result)
    End Function

    Public Function empty(ByVal result As pointer(Of Boolean)) As eventComb Implements islice.empty
        Return s.empty(result)
    End Function

    Public Function retire(ByVal result As pointer(Of Boolean)) As eventComb Implements islice.retire
        Return s.retire(result)
    End Function

    Public Function capacity(ByVal result As pointer(Of Int64)) As eventComb Implements islice.capacity
        Return s.capacity(result)
    End Function

    Public Function valuesize(ByVal result As pointer(Of Int64)) As eventComb Implements islice.valuesize
        Return s.valuesize(result)
    End Function

    Public Function keycount(ByVal result As pointer(Of Int64)) As eventComb Implements islice.keycount
        Return workon(Function(ByRef p As pointer(Of Int64)) As eventComb
                          Return s.keycount(p)
                      End Function,
                      Function(ByRef r As Boolean, ByRef i As Int64) As Boolean
                          If r Then
                              Return eva(result, i >> 1)
                          Else
                              Return eva(result, npos)
                          End If
                      End Function)
    End Function

    Public Function heartbeat(ByVal result As pointer(Of Boolean)) As eventComb Implements islice.heartbeat
        Return s.heartbeat(result)
    End Function

    Public Sub [stop]() Implements islice.stop
        s.stop()
    End Sub
End Class
